import { Component } from 'react'
import PropTypes from 'prop-types'
import { defaultProps } from '../types/baseType'

interface CountType {
	count: number
}

interface PosType {
	pos: {
		x: number
		y: number
	}
}

type Props = defaultProps & {
	msg: string
}

class Child extends Component<CountType> {
	UNSAFE_componentWillReceiveProps(nextProps: CountType) {
		console.log('componentWillReceiveProps', nextProps)
	}

	componentWillUnmount() {}

	render() {
		return (
			<div
				style={{
					border: 'solid 1px black',
					margin: '10px',
					padding: '10px',
				}}
			>
				Child 组件
				<div>Child count:{this.props.count}</div>
			</div>
		)
	}
}

export default class LifeCycle extends Component<Props, CountType> {
	static defaultProps = {
		msg: 'haha',
	}
	static propTypes = {
		msg: PropTypes.string.isRequired,
	}

	constructor(props: Props) {
		super(props)
		this.state = {
			count: 0,
		}
	}

	// 初始化/卸载
	UNSAFE_componentWillMount() {
		// 废弃生命周期钩子，react17 已停止使用
		console.log('UNSAFE_componentWillMount', this.state)
	}

	componentDidMount() {
		console.log('componentDidMount', this.state.count)
	}

	componentWillUnmount() {
		// 考点0：组件卸载时执行，移除定时器、事件等
		console.log('componentWillUnmount', this.state)
	}

	// 更新时
	static getDerivedStateFromProps(props: Props, state: CountType) {
		// 考点1：getDerivedStateFromProps 会在调用 render 方法之前调用，并且在初始挂载及后续更新时都会被调用。
		//它应返回一个对象来更新 state，如果返回 null 则不更新任何内容。
		console.log('getDerivedStateFromProps:', props, state)
		const { count } = state
		return count < 5 ? null : { count: 0 }
	}

	shouldComponentUpdate(nextProps: Props, nextState: CountType) {
		// 考点2：shouldComponentUpdate 判断组件是否需要更新。
		// PureComponent 默认设置 shouldComponentUpdate 针对 props/state 浅比较判断是否更新。深层对象需要自定义 shouldComponentUpdate。
		const { count } = nextState
		console.log('shouldComponentUpdate:', nextProps, nextState)
		return count !== 3
	}

	// 子组件执行 UNSAFE_componentWillReceiveProps

	UNSAFE_componentWillUpdate() {
		// 考点3： react17 及以上停止使用
		console.log('componentWillUpdate', this.state)
	}

	getSnapshotBeforeUpdate(prevProps: Props, prevState: CountType) {
		// 考点4： 在 dom 渲染到屏幕之前执行，获取 dom 更新之前的相关信息。并且返回值将传递给  componentDidUpdate 第三个参数
		console.log('getSnapshotBeforeUpdate:', prevProps, prevState)
		return { pos: { x: 100, y: 101 } }
	}

	componentDidUpdate(prevProps: Props, prevState: CountType, pos: PosType) {
		// 考点5：dom渲染到屏幕之后执行，可以获取 getSnapshotBeforeUpdate 传递过来的第三个参数。
		console.log('componentDidUpdate: ', pos, prevProps, prevState)
	}

	setCount = () => {
		this.setState({
			count: this.state.count + 1,
		})
	}

	render() {
		const { count } = this.state

		return (
			<div>
				<h1>LifeCycle 页面</h1>
				<p>{count}</p>
				<button onClick={this.setCount}> 改变 count</button>
				<Child count={count} />
			</div>
		)
	}
}
